<?php
//通用函数库类
class common
{
	
	//程序中断，输出错误信息
	public static function stop($warning){
		header("content-type:text/html;charset=utf-8");
		die($warning);
	}
	
	//传递表单数组处理补全,$data=原数组，$fixer=补丁数组
	public static function sendfix($data = array(),$fixer = array()){
		if (empty($data)){
			if ($_POST){
				$data = $_POST;
			}elseif ($_GET){
				$data = $_GET;
			}else{
				return false;
			}
		}
		$data = array_merge($fixer,$data);
		$return = array();
		foreach ($data as $k=>$v){
			if (is_string($v)){
				$return[$k] = addslashes(trim($v));
			}else{
				$return[$k] = $v;
			}
		}
		return $return;
	}
	
	//文件备份，名字用日期时间区别
	public static function fileBackup($file){
		$date = date('Y-m-d');
		$dir = dirname($file);
		if (!is_writable($dir)){
			return false;
		}
		$filename = self::fileprename($file);
		$fileext = self::fileext($file);
		$dest = $dir.'/'.$filename.$date.'.'.$fileext;
		if (!copy($file,$dest)){
			return copy($file,$dest);
		}
		return false;
	}
	
	//文件或者文件夹附加目录分隔符抬头
	public static function pathpad($path,$root = true){
		$path = ltrim($path,'/\ ');
		if ($root) $path = '/'.$path;
		return $path;
	}
	
	//网址附加http抬头
	public static function urlpad($url,$slash = false){
        $url = (0 === stripos($url,'http')?trim($url,' /'):'http://'.trim($url,' /'));
        if ($slash) $url .= '/';
        return $url;
    }
    
	public static function msg($msg = '',$url = ''){
		$msg = $msg?$msg:'系统出错！请重试';
		echo '<script>alert("'.$msg.'");</script>';
		if ($url){
			echo '<script>location.href="'.$url.'";</script>'; 
			exit;
		}
	}
	
	//获取ip地址
	public static function getip(){
		$onlineipmatches = array();
		if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $onlineip = getenv('HTTP_CLIENT_IP');
        } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $onlineip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
            $onlineip = getenv('REMOTE_ADDR');
        } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $onlineip = $_SERVER['REMOTE_ADDR'];
        }
        $onlineip = addslashes($onlineip);
        @preg_match("/[\d\.]{7,15}/", $onlineip, $onlineipmatches);
        $onlineip = isset($onlineipmatches[0])?$onlineipmatches[0]:'unknown';
        unset($onlineipmatches);
        return $onlineip;
	}
	
	//在线获取服务器端IP
	public static function getlocalip(){
		if (extension_loaded('curl')){
			$ch = curl_init('http://www.ip138.com/ips138.asp');
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			$output = curl_exec($ch);
	        curl_close($ch);
	        if (preg_match_all('/\[(.+)\]/', $output, $m))
	        {
	            foreach ($m[1] as $output){
	            	if (preg_match('/^[\d\.]+$/',$output,$s)){
	            		return $s[0];
	            	}
	            }
	        }
		}
		return false; 
	}

	/* 
    * <input type="file" name="pic[test]" />
    * 
    * $rename = true//自动随机文件名,$rename = 'string'//自定义文件名,$rename = false//保留原文件名
    * $cover = true//重名的话覆盖原文件
    * 
    * $key_type = FILE_NAME_KEY
    * array (size=1)
    * 	'ownfire密保卡450540010840734.jpg' => string 'uploadFile/2012-10-18/pooqPhUWov.jpg'
    * 
    * $key_type = HTML_NAME_KEY
    * array (size=1)
    * 	'test' => string 'uploadFile/2012-10-18/d1wcYQOMCv.jpg'
    * */
	//上传文件上层处理
    public static function upload($name,$strExt = null,$dir = null,$rename = true,$cover = false,$key_type = FILE_NAME_KEY,$dateDir = true)
    {
        if (!$_FILES || !isset($_FILES[$name]) || empty($_FILES[$name]['tmp_name']))
            return false;
        if (!$dir)
            $dir = project::config()->uploadDir;
    	$files = array();
        if (is_array($_FILES[$name]['tmp_name'])){
            foreach ($_FILES[$name]['tmp_name'] as $k=>$tmp_name){
                if (!$tmp_name) continue;
                $fileinfo = array(
                	'name'=>$_FILES[$name]['name'][$k],
                    'type'=>$_FILES[$name]['type'][$k],
                    'tmp_name'=>$_FILES[$name]['tmp_name'][$k],
                    'error'=>$_FILES[$name]['error'][$k],
                    'size'=>$_FILES[$name]['size'][$k]
                );
                if (is_file($file = self::uploadhanding($fileinfo,$dir,$strExt,$dateDir,$rename,$cover))){
                	if ($key_type == 1){
                		$files[$k] = $file;
                	}else{
                		$files[$_FILES[$name]['name'][$k]] = $file;
                	}
                }
            }
        }else{
        	if (is_file($file = self::uploadhanding($_FILES[$name],$dir,$strExt,$dateDir,$rename,$cover))){
        		if ($key_type == 1){
        			$files = array($name=>$file);
        		}else{
        			$files = array($_FILES[$name]['name']=>$file);
        		}
        	}
        }
        return $files;
    }
    
    //上传文件底层处理
    private static function uploadhanding($fileinfo,$dir,$strExt = null,$dateDir = false,$rename = true,$cover = false){
        try {
            //$dir = 上传目录
            if (! is_uploaded_file($fileinfo['tmp_name']))
            {
                throw e('上传失败');
            }
            $ext = strtolower(common::fileext($fileinfo['name']));
            if ($strExt)
            {
                if (is_string($strExt) && ($strExt != $ext)){
                    throw e('错误的文件扩展名:'.$ext);
                }
                if (is_array($strExt) && !in_array($ext,$strExt)){
                    throw e('错误的文件扩展名:'.$ext);
                }
            }
            if (! is_dir($dir))
            {
                if (! mkdir($dir,0777,true))
                {
                    throw e('创建上传文件目录失败:'.$dir);
                }
            }elseif (!is_writable($dir)){
                throw e('上传文件目录不可写:'.$dir);
            }
            
            if($dateDir){
                    $dir .= '/'.date('Y-m-d');
                    if (! is_dir($dir))
                    {
                        if (! mkdir($dir,0777,true))
                        {
                            throw e('创建上传文件日期目录失败:'.$dir);
                        }elseif (!is_writable($dir)){
                                throw e('上传文件日期目录不可写:'.$dir);
                            }
                    }
            }
            
            if (is_string($rename) && $rename)
                $filename = $rename;
            elseif ($rename === false)
                $filename = $fileinfo['name'];
            else
                $filename = self::randfilename() . '.' . $ext;
            
            $file = $dir . '/' . $filename;
            if (is_file($file) && $cover)
                @unlink($file);
            if (move_uploaded_file($fileinfo['tmp_name'], $file))
            {
                return $file;//最终传递文件全路径
            }else
            {
                throw e('上传文件转移失败:'.$file);
            }
            return false;
        } catch (e $e) {
            $e->throwing();
        }
    }
	
    //获取不带扩展名的文件名
    public static function fileprename($filename){
    	return basename($filename,'.'.pathinfo($filename,PATHINFO_EXTENSION));
    }
    
    //获取文件扩展名
    public static function fileext($filename){
        return pathinfo($filename,PATHINFO_EXTENSION);
    }
		
	//产生随机字符串
	public static function randStr($len = 6, $format = 'ALL') {
		switch ($format) {
			case 'ALL' :
				$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
				break;
			case 'CHAR' :
				$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
				break;
			case 'NUMBER' :
				$chars = '0123456789';
				break;
			default :
				$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
				break;
		}
		$string = "";
		while ( strlen ( $string ) < $len )
			$string .= substr ( $chars, (mt_rand () % strlen ( $chars )), 1 );
		return $string;
	}
	
    //返回随机文件名
    public static function randfilename($length = 10)
    {
        $hash = '';
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
        $max = strlen($chars) - 1;
        //mt_srand((double) microtime() * 1000000);
        for($i = 0;$i < $length;$i ++)
        {
            $hash .= $chars[mt_rand(0, $max)];
        }
        return $hash;
    }
    
    //CURL数据传输
    public static function curl($url,array $params = array()){
        if (!$url){
            return '';
        }
        $init = curl_init();
        curl_setopt($init,CURLOPT_URL,$url);
        curl_setopt($init,CURLOPT_RETURNTRANSFER,true);
        curl_setopt ( $init, CURLOPT_SSL_VERIFYPEER, 0 );
        curl_setopt ( $init, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 (.NET CLR 3.5.30729)" );
	    //curl_setopt ( $init, CURLOPT_HEADER, false );
	    //curl_setopt ( $init, CURLOPT_NOBODY, false );
	    curl_setopt ( $init, CURLOPT_FOLLOWLOCATION, 1 ); // 使用自动跳转
        if (count($params)){
            curl_setopt($init,CURLOPT_POST,true);
            curl_setopt($init,CURLOPT_POSTFIELDS,$params);
        }
        $result = curl_exec($init);
        if ($error = curl_errno ( $init )) {
		    //echo 'curl error:' . $error;
		    //return 'ERROR';
		    return '';
	    }
        curl_close($init);
        return $result;
    }
    
    function post($url,$post_data = null,$port = 80,$return = false){
        $url_info = parse_url($url);
        //var_dump($url_info);
        if (!$url_info)
            return false;
        $host = isset($url_info['host'])?$url_info['host']:$url_info['path'];
        $port = isset($url_info['port'])?$url_info['port']:$port;
        $uri = (isset($url_info['host']) && isset($url_info['path']))?$url_info['path']:'/';
        $query = isset($url_info['query'])?'?'.$url_info['query']:'';
        
        if (is_array($post_data))
            $post_data = http_build_query($post_data);
        else
            $post_data = (string)$post_data;
        
        $header = "POST {$uri}{$query}  HTTP/1.1\r\n";
        $header .= "Host: $host\r\n";
        $header .= "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)\r\n";//浏览器标识
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: ".strlen($post_data)."\r\n";
        $header .= "Connection: close\r\n\r\n";
        $header .= $post_data;
        //echo $header;
        
        $fp = fsockopen($host, $port, $errno, $errstr);
        //$fp = stream_socket_client($host.':'.$port, $errno, $errstr);
        if (!$fp) {
           echo "$errstr ($errno)<br/>\n";
           echo $fp;
        } else {
            fputs($fp, $header);
            if ($return){
                $r = '';
                while (!feof($fp))
                    $r .= fgets($fp, 128);
            }else{
                $r = true;
            }
            fclose($fp);
            return $r;
        }
    }

    //截取一定长度的字符串，确保截取后字符串不出乱码
	public static function cutstr($str,$len,$ending = '....')
    {
    	if (extension_loaded("mbstring")){
    		$charset = strtoupper(project::config('config')->charset);
    		return mb_strlen($str,$charset)<=$len ? $str : (mb_substr($str,0,$len,$charset)."....");
    	}
    	return strlen($str)<=$len ? $str : (substr($str,0,$len).$ending);
    }
    
    //load extension
    public static function dl($ext,$or_ext = null){
    	if (extension_loaded($ext)) return true;
    	if (!function_exists('dl')){
    		if (!(bool)ini_get('enable_dl') || (bool)ini_get('safe_mode')) return false;
    	}
    	$ext = ((PHP_SHLIB_SUFFIX === 'dll')?'php_':'').$ext.'.'.PHP_SHLIB_SUFFIX;
    	if (dl($ext)) return true;
    	if (!$or_ext) return false;
    	$or_ext = ((PHP_SHLIB_SUFFIX === 'dll')?'php_':'').$or_ext.'.'.PHP_SHLIB_SUFFIX;
    	return dl($or_ext);
    }
	
	//将内容进行UNICODE编码，编码后的内容格式：YOKA\王 （原始：YOKA王）
	public static function unicode_encode($s) {
		$s = iconv ( 'UTF-8', 'UCS-2', $s );
		$len = strlen ( $s );
		$str = '';
		for($i = 0; $i < $len - 1; $i = $i + 2) {
			$c = $s [$i];
			$c2 = $s [$i + 1];
			if (ord ( $c ) > 0) { // 两个字节的文字
				$str .= '\u' . base_convert ( ord ( $c ), 10, 16 ) . base_convert ( ord ( $c2 ), 10, 16 );
			} else {
				$str .= $c2;
			}
		}
		return $str;
	}
	
    //unicode解码
	public static function unicode_decode($str) {
		preg_match_all ( '/\\\u([[:alnum:]]{4})/', $str, $a );
		foreach ( $a [1] as $uniord ) {
			$dec = hexdec ( $uniord );
			$utf = '';
			if ($dec < 128) {
				$utf = chr ( $dec );
			} else if ($dec < 2048) {
				$utf = chr ( 192 + (($dec - ($dec % 64)) / 64) );
				$utf .= chr ( 128 + ($dec % 64) );
			} else {
				$utf = chr ( 224 + (($dec - ($dec % 4096)) / 4096) );
				$utf .= chr ( 128 + ((($dec % 4096) - ($dec % 64)) / 64) );
				$utf .= chr ( 128 + ($dec % 64) );
			}
			$str = str_replace ( '\u' . $uniord, $utf, $str );
		}
		return ($str);
	}
	
	//根据给定间隔项分开数组
	public static function array_explode($delimiter,array $array,$limit = null){
		$new = array();
		$new_row = &$new[];
		$count = 1;
		foreach ($array as $row){
			if (($row == $delimiter) && (($limit == null) || $count<$limit)){
				$new_row = &$new[];
				$count++;
				continue;
			}
			$new_row[] = $row;
		}
		return $new;
	}
	
	//去掉数组首尾等值为FALSE的条目
	public static function array_trim($array){
        if ((bool)current($array) === false)
            array_shift($array);
        if ((bool)end($array) === false)
            array_pop($array);
        return $array;
	}
	
	//根据给定字符遍历数组拼接深层的值，返回拼接后的字符串
	public static function array_deep_implode($glue, array $pieces,array $zones){
		$t = '';
		$current = current($pieces);
		while ($current){
			$_t = self::array_deep($current, $zones);
			if (!$_t) continue;
			$t .= $_t;
			if ($current = next($pieces)) 
				$t .= $glue;
		}
		return $t;
	}
	
	//解析get请求串
	public static function parse_str($get){
		$arr = explode('&', trim($get,'&'));
		$new = array();
		foreach ($arr as $arr){
			$arr = explode('=', $arr);
			if (isset($arr[1]))
				$new[$arr[0]] = $arr[1];
			else
				$new[] = $arr[0];
		}
		return $new;
	}
	
	//使用一个字符串分割另一个字符串，并且过滤结果数组中的等值为FALSE的条目，并且将结果数组的每一项去首尾空格
	public static function explode($delimiter,$string,$limit = null){
		if (is_int($limit))
			$pieces = array_filter(explode($delimiter,$string,$limit));
		else
			$pieces = array_filter(explode($delimiter,$string));
		foreach ($pieces as &$piece){
			$piece = trim($piece);
		}
		return $pieces;
	}
	
	//根据给定的各个层级的键返回数组深层的值
	public static function array_deep(array $array,array $zones){
		$value = $array;
		foreach ($zones as $zone){
			if (!isset($array[$zone])) false;
			$value = $value[$zone];
		}
		return $value;
	}
	
	//根据给定的各个层级的键合并数组深层的值
	public static function array_deep_merge(array $zones){
		$arrays = func_get_args();
		array_shift($arrays);
		$result = array();
		foreach ($arrays as $array){
			foreach ($zones as $zone){
				if (!isset($array[$zone])) false;
				$array = $array[$zone];
			}
			$result = array_merge($result,$array);
		}
		return $result;
	}
	
	//根据给定的各个层级的键合并一个数组每一项深层的值
	public static function array_deep_combat(array $zones,array $arrays){
		$result = array();
		foreach ($arrays as $array){
			foreach ($zones as $zone){
				if (!isset($array[$zone])) false;
				$array = $array[$zone];
			}
			//var_export($array);
			$result = array_merge($result,$array);
		}
		return $result;
	}
}